package com.cy.system.shiro;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import org.springframework.beans.factory.annotation.Autowired;

import com.cy.commons.utils.EncryptUtil;
import com.cy.system.entity.Account;
import com.cy.system.entity.Permission;
import com.cy.system.entity.Role;
import com.cy.system.entity.User;
import com.cy.system.service.AccountService;
import com.cy.system.service.PermissionService;
import com.cy.system.service.RoleService;
import com.cy.system.service.UserService;

public class MyRealm extends AuthorizingRealm{
	
	private final static Logger logger = Logger.getLogger(MyRealm.class);
	
	@Autowired
    private UserService userService;
	
	@Autowired
	private AccountService accountService;
	
	@Resource
	private RoleService roleService;
    
    @Autowired
    private PermissionService permissionService;
	
	/**
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 获取用户名
    	UsernamePasswordToken UPToken = (UsernamePasswordToken) token;
    	logger.info("==> 获取登录令牌["+UPToken+"]");
        String loginName = (String) token.getPrincipal();
        logger.info("==> 读取账号[" + loginName + "]权限...");
        // 通过用户名获取用户对象
        Account account = accountService.getAccountByLoginName(loginName);
        logger.info("==> 从数据库获取账号信息["+account+"]");
        if (account == null) {
        	logger.error("==> 账号不存在！["+account+"]");	
            return null;
        }
        
        // 通过 userId 获取该用户拥有的所有权限，返回值根据自己需求编写，并非固定值。
        //Map<String,List<Permission>> permissionMap = this.permissionService.getPermissionMapByUserId(user.getUserId());
        
        // （目录+菜单，分层级，用于前端 jsp 遍历）
        /*user.setMenuList(permissionMap.get("menuList"));*/
        // （目录+菜单+按钮，用于后端权限判断）
        /*user.setPermissionList(permissionMap.get("permissionList"));*/
        byte[] salt = EncryptUtil.decodeHex((String)account.getPassword().subSequence(0, 16));
        SimpleAuthenticationInfo info =
				new SimpleAuthenticationInfo(account,account.getPassword().substring(16),
							ByteSource.Util.bytes(salt),getName());
        logger.info("==> 返回认证信息[" + info + "]");
        return info;
    }
    
    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        Account account = (Account) principals.getPrimaryPrincipal();
        logger.info("==> 进入授权方法，获取凭证信息[" + account + "]");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        User user = userService.getUserByAccountId(account.getAccountId());
        List<Integer> roleIds = userService.getUserRoleIds(user.getUserId());
        logger.info("==> 获取roleIds[" + roleIds + "]");
        // （目录+菜单+按钮，用于后端权限判断）
        /*List<Permission> permissionList = user.getPermissionList();*/
        
        /*for (Permission permission : permissionList) {
            if (StringUtil.isNotEmpty(permission.getCode())) {
                info.addStringPermission(permission.getCode());
            }
        }*/
        List<String> roleNameList = new ArrayList<String>();
        for(Integer roleId : roleIds) {
        	Role role = roleService.getRoleById(roleId);
        	if(null!=role) {
        		roleNameList.add(role.getRoleName());
        	}
        	
        }
        info.addRoles(roleNameList);
        logger.info("==> 设置权限，角色集合roleNameList[" + roleNameList + "]");
        return info;
    }
}
